home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dutil / save / fdtolib.c < prev    next >
C/C++ Source or Header  |  1994-01-30  |  21KB  |  1,013 lines

  1.  
  2. /*
  3.  *  FDTOLIB.C
  4.  *
  5.  * (c)Copyright 1992 Obvious Implementations Corp, All Rights Reserved
  6.  *
  7.  *  FDTOLIB fdfile[s] [-h hdrfile] -o libname [-mr] [-mD] [-pprefix] -I incldir
  8.  *            -prof -mc -mC -auto libname -AUTO libname
  9.  *
  10.  *  Generates a normal model or registerized modem library interface given
  11.  *  any set of FD files.
  12.  *
  13.  *  -ms, -r, and -pr are ignored
  14.  */
  15.  
  16. #ifndef unix
  17. #include <exec/types.h>
  18. #include <exec/nodes.h>
  19. #include <exec/lists.h>
  20. #endif
  21. /*#include <clib/alib_protos.h>*/
  22. #ifndef LATTICE
  23. #ifndef unix
  24. #include <clib/exec_protos.h>
  25. #include <clib/dos_protos.h>
  26. #include <clib/alib_protos.h>
  27. #endif
  28. #else
  29. #include <proto/exec.h>
  30. #include <proto/dos.h>
  31. #endif
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <lib/profile.h>
  36. #include <lib/version.h>
  37.  
  38. #ifdef unix
  39. #include <../suplib/all.h>
  40. #endif
  41.  
  42. #ifndef L_tmpnam
  43. #define L_tmpnam    64
  44. #endif
  45.  
  46. #define RF_SCRATCH  0x0303
  47. #define RB_BP        (8+6)
  48. #define RF_BP        (1 << RB_BP)
  49.  
  50. #ifdef _DCC
  51. IDENT("fdtolib", ".5");
  52. DCOPYRIGHT;
  53. #endif
  54.  
  55. typedef unsigned short uword;
  56. typedef struct List    List;
  57. typedef struct Node    Node;
  58.  
  59. typedef struct LVONode {
  60.     Node    lv_Node;
  61.     short   lv_Offset;
  62. } LVONode;
  63.  
  64. typedef struct RSNode {
  65.     Node    rn_Node;
  66.     short   rn_Args;        /*    -1 specifies stack  */
  67.     short   rn_Flag;        /*    equiv/fd found        */
  68.     short   rn_Regs[32];    /*    transfer registers  */
  69. } RSNode;
  70.  
  71. void    help(int);
  72. void    ScanFD(FILE *, FILE *);
  73. void    ScanRSTmp(FILE *);
  74. void    GenerateFunction(FILE *, char *, char *, int);
  75. int    AssembleFile(char *, char *);
  76. void    JoinOutput(FILE *, char *);
  77. char    *RegMaskToStr(uword, short *);
  78. uword    RegsToMask(short *, short);
  79. char    *RegToStr(short);
  80. void    RegsCall(FILE *, char *, long, RSNode *, short *);
  81. void    StackCall(FILE *, char *, long, short *, short);
  82. short    PushMask(FILE *, uword);
  83. short    PopMask(FILE *, uword);
  84. void    AddLVOList(char *, int);
  85. void    GenerateLVOList(FILE *);
  86. void    GenerateAutoOpen(FILE *, char *);
  87. void    DicePrefix(char *, char *, char *);
  88.  
  89. List    FDList;     /*  list of FD files   */
  90. List    RSList;     /*  register spec list */
  91. List    LVOList;
  92. char    DccOptsBuf[1024];
  93. char    *OutFile;
  94. char    *HdrFile;
  95. char    *FuncPrefix = "_";
  96. char    Buf[256];
  97. char    FuncName[256];
  98. char    Prefix[64];
  99. short    RegOpt;
  100. short    Verbose;
  101. short    SmallData = 1;
  102. short    SmallCode = 1;
  103. short    ProfOpt;
  104. short    AutoOpt;
  105. char    *DataModel = "(A4)";
  106. char    *CodeModel = "(PC)";
  107. char    *SharedLibName;
  108.  
  109. main(ac, av)
  110. int  ac;
  111. char **av;
  112. {
  113.     int i;
  114.  
  115.     NewList(&FDList);
  116.     NewList(&RSList);
  117.     NewList(&LVOList);
  118.  
  119.     DicePrefix(Prefix, av[0], "");
  120.  
  121. #ifndef LATTICE
  122. #ifndef unix
  123.     expand_args(ac, av, &ac, &av);
  124. #endif
  125. #else
  126.     setbuf(stdout, NULL);
  127. #endif
  128.  
  129.     for (i = 1; i < ac; ++i) {
  130.     char *ptr = av[i];
  131.  
  132.     if (*ptr != '-') {
  133.         Node *node = malloc(sizeof(Node));
  134.         node->ln_Name = ptr;
  135.         AddTail(&FDList, node);
  136.         continue;
  137.     }
  138.     ptr += 2;
  139.     switch(ptr[-1]) {
  140.     case 'a':
  141.         AutoOpt = 1;
  142.         SharedLibName = av[++i];
  143.         break;
  144.     case 'A':
  145.         AutoOpt = 2;
  146.         SharedLibName = av[++i];
  147.         break;
  148.     case 'p':
  149.         if (strcmp(ptr, "rof") == 0)
  150.         ProfOpt = 1;
  151.         else if (strcmp(ptr, "r") == 0)     /*  ignore -pr  */
  152.         ;
  153.         else
  154.         FuncPrefix = (*ptr) ? ptr : av[++i];
  155.         break;
  156.     case 'o':
  157.         OutFile = (*ptr) ? ptr : av[++i];
  158.         break;
  159.     case 'h':
  160.         HdrFile = (*ptr) ? ptr : av[++i];
  161.         break;
  162.     case 'm':
  163.         if (*ptr == 'r' || *ptr == 'R')
  164.         RegOpt = 1;
  165.         else if (*ptr == 'd') {
  166.         SmallData = 1;
  167.         DataModel = "(A4)";
  168.         } else if (*ptr == 'D') {
  169.         SmallData = 0;
  170.         DataModel = "";
  171.         } else if (*ptr == 'c') {
  172.         SmallCode = 1;
  173.         CodeModel = "(pc)";
  174.         } else if (*ptr == 'C') {
  175.         SmallCode = 0;
  176.         CodeModel = "";
  177.         } else if (*ptr == 's') {
  178.         /*  ignore  */
  179.         }
  180.         break;
  181.     case 'r':
  182.         /* ignore -r    */
  183.         break;
  184.     case 'v':
  185.         ++Verbose;
  186.         break;
  187.     case 'I':
  188.         sprintf(DccOptsBuf + strlen(DccOptsBuf), " -I%s", (*ptr) ? ptr : av[++i]);
  189.         break;
  190.     default:
  191.         help(1);
  192.     }
  193.     }
  194.     if (OutFile == NULL || (RegOpt && HdrFile == NULL))
  195.     help(ac != 1);
  196.  
  197.     if (RegOpt == 0 && HdrFile)
  198.     puts("Warning: header file ignored (used only with -mr)");
  199.  
  200.     /*
  201.      *    step 2, ask DCC to generate a register specification file
  202.      */
  203.  
  204.     if (RegOpt) {
  205.     FILE *fi;
  206.     char rs_tmp[L_tmpnam];
  207.  
  208.     sprintf(Buf, "%sdcc -mRRX %s -a -o %s%s",
  209.         Prefix,
  210.         HdrFile,
  211.         tmpnam(rs_tmp),
  212.         DccOptsBuf
  213.     );
  214.     puts(Buf);
  215. #ifdef unix
  216.         system(Buf);
  217. #else
  218.     Execute(Buf, NULL, NULL);
  219. #endif
  220.  
  221.     if ((fi = fopen(rs_tmp, "r")) == NULL) {
  222.         puts("Unable to generate register specification file");
  223.         help(20);
  224.     }
  225.     ScanRSTmp(fi);
  226.     fclose(fi);
  227.     remove(rs_tmp);
  228.     }
  229.  
  230.     /*
  231.      *    step 3
  232.      */
  233.  
  234.  
  235.     {
  236.     FILE *fi;
  237.     FILE *fo = fopen(OutFile, "w");
  238.     Node *node;
  239.  
  240.     if (fo == NULL) {
  241.         printf("Error, Unable to create %s\n", OutFile);
  242.         exit(20);
  243.     }
  244.     while (node = RemHead(&FDList)) {
  245.         printf("generate %s", node->ln_Name);
  246.         fi = fopen(node->ln_Name, "r");
  247.         if (fi) {
  248.         puts("");
  249.         ScanFD(fi, fo);
  250.         fclose(fi);
  251.         } else {
  252.         puts(" (open failed)");
  253.         }
  254.     }
  255.     }
  256.     {
  257. #ifdef NOTDEF
  258.     RSNode *rs;
  259.  
  260.     for (rs = RSList.lh_Head; rs->rn_Node.ln_Succ; rs = (RSNode *)rs->rn_Node.ln_Succ) {
  261.         if (rs->rn_Flag == 0)
  262.         printf("Warning, no FD entry found for: %s\n", rs->rn_Node.ln_Name);
  263.     }
  264. #endif
  265.     }
  266.     return(0);
  267. }
  268.  
  269. void
  270. help(code)
  271. {
  272. #ifdef _DCC
  273.     puts(Ident);
  274. #endif
  275.     puts("FDTOLIB files/wildcard [-h hdrfile] -o libname [-mr] [-mD]");
  276.     puts("  -mr :   generate registered library from header & fd file");
  277.     puts("  -mD :   large data model (else small data model)");
  278.     exit(code);
  279. }
  280.  
  281. void
  282. ScanFD(fi, fo)
  283. FILE *fi;
  284. FILE *fo;
  285. {
  286.     char *base = NULL;
  287.     long bias = -1;
  288.     short end = 0;
  289.     short public = 1;
  290.  
  291.     char *key;
  292.  
  293.     while (fgets(Buf, sizeof(Buf), fi)) {
  294.     if (Buf[0] == '\n' || Buf[0] == '*')
  295.         continue;
  296.     if (strncmp(Buf, "##", 2) != 0) {
  297.         if (bias < 0 || base == NULL) {
  298.         printf("Error, No ##base/##bias before function: %s\n", Buf);
  299.         continue;
  300.         }
  301.         if (public && AutoOpt != 2)
  302.         GenerateFunction(fo, Buf, base, bias);
  303.         bias += 6;
  304.         continue;
  305.     }
  306.     if ((key = strtok(Buf + 2, " \t\n")) == NULL) {
  307.         printf("\tError, Illegal null directive\n");
  308.         continue;
  309.     }
  310.     if (stricmp(key, "base") == 0) {
  311.         if (key = strtok(NULL, " \t\n")) {
  312.         if (base)
  313.             free(base);
  314.         base = strdup(key);
  315.         } else {
  316.         printf("\tError, Illegal ##base directive\n");
  317.         }
  318.         continue;
  319.     }
  320.     if (stricmp(key, "bias") == 0) {
  321.         if (key = strtok(NULL, " \t\n")) {
  322.         char *dummy;
  323.  
  324.         bias = strtol(key, &dummy, 0);
  325.         if (bias <= 0)
  326.             printf("\tError, Illegal ##bias: %d\n", bias);
  327.         } else {
  328.         printf("\tError, Illegal ##bias directive\n");
  329.         }
  330.         continue;
  331.     }
  332.     if (stricmp(key, "public") == 0) {
  333.         public = 1;
  334.         continue;
  335.     }
  336.     if (stricmp(key, "private") == 0) {
  337.         public = 0;
  338.         continue;
  339.     }
  340.     if (stricmp(key, "end") == 0) {
  341.         end = 1;
  342.         break;
  343.     }
  344.     printf("\tError, Unrecognized directive: %s\n", key);
  345.     }
  346.     if (bias < 0)
  347.     puts("\tUnexpected EOF, no ##bias");
  348.     if (base == NULL)
  349.     puts("\tUnexpected EOF, no ##base");
  350.     if (end == 0)
  351.     puts("\tUnexpected EOF, no ##end directive");
  352.     if (AutoOpt != 2)
  353.     GenerateLVOList(fo);
  354.     if (AutoOpt)
  355.     GenerateAutoOpen(fo, base);
  356. }
  357.  
  358. /*
  359.  *  funcname(var,var,var)(reg,reg,reg)        (or reg/reg)
  360.  */
  361.  
  362. static short    FRegs[128];
  363.  
  364. void
  365. GenerateFunction(fo, buf, base, bias)
  366. FILE *fo;
  367. char *buf;
  368. char *base;
  369. int bias;
  370. {
  371.     char tmpFile[L_tmpnam];
  372.     char objFile[L_tmpnam+4];
  373.     char *funcName;
  374.     FILE *ft;
  375.     short argCnt;
  376.     short noArgs = 0;
  377.  
  378.     funcName = buf;
  379.     while (*funcName && *funcName != '\t' && *funcName != ' ' && *funcName != '(')
  380.     ++funcName;
  381.     if (*funcName == ' ' || *funcName == '\t') {
  382.     while (*funcName && *funcName != '(')
  383.         *funcName++ = 0;
  384.     }
  385.     if (*funcName == '(') {
  386.     *funcName++ = 0;
  387.     if (*funcName == ')')
  388.         noArgs = 1;
  389.     }
  390.     while (*funcName && *funcName != ')')   /*  skip text args  */
  391.     ++funcName;
  392.     while (*funcName && *funcName != '(')
  393.     ++funcName;
  394.     if (noArgs == 0 && *funcName == 0) {
  395.     printf("\tError in line: %s\n", buf);
  396.     return;
  397.     }
  398.  
  399.     /*
  400.      *    get register description
  401.      */
  402.  
  403.     if (*funcName)
  404.     ++funcName;
  405.     for (argCnt = 0; *funcName && *funcName != '\n' && *funcName != ')'; ++argCnt) {
  406.     switch(*funcName) {
  407.     case 'd':
  408.     case 'D':
  409.         FRegs[argCnt] = *++funcName - '0';
  410.         ++funcName;
  411.         break;
  412.     case 'a':
  413.     case 'A':
  414.         FRegs[argCnt] = *++funcName - '0' + 8;
  415.         ++funcName;
  416.         break;
  417.     default:
  418.         printf("\tError in register spec: %s\n", funcName);
  419.         return;
  420.     }
  421.     if (*funcName == ',' || *funcName == '/')
  422.         ++funcName;
  423.     }
  424.     if (noArgs == 0 && *funcName != ')') {
  425.     printf("\tError in register spec: %s\n", funcName);
  426.     return;
  427.     }
  428.  
  429.     /*
  430.      *    generate
  431.      */
  432.  
  433.     funcName = strdup(buf);
  434.     {
  435.     RSNode *rs;
  436.  
  437.     if (Verbose)
  438.         printf("    %-15s %d %d ", funcName, -bias, argCnt);
  439.  
  440.     if (RegOpt) {
  441.         for (rs = (RSNode *)RSList.lh_Head; rs->rn_Node.ln_Succ; rs = (RSNode *)rs->rn_Node.ln_Succ) {
  442.         if (strcmp(rs->rn_Node.ln_Name + 1, funcName) == 0) {
  443.             rs->rn_Flag = 1;
  444.             break;
  445.         }
  446.         }
  447.         if (rs->rn_Node.ln_Succ == NULL) {    /* (list tail)    */
  448.         if (Verbose)
  449.             puts("NO MATCH FOUND");
  450.         return;
  451.         }
  452.  
  453.         if (rs->rn_Args >= 0 && rs->rn_Args != argCnt) {
  454.         printf("Error, argCnt mismatch %s (%d/%d)\n", rs->rn_Node.ln_Name, rs->rn_Args, argCnt);
  455.         return;
  456.         }
  457.     }
  458.     if (Verbose)
  459.         fflush(stdout);
  460.  
  461.     tmpnam(tmpFile);
  462.     sprintf(objFile, "%s.o", tmpFile);
  463.  
  464.     if (RegOpt)
  465.         sprintf(FuncName, "%s", rs->rn_Node.ln_Name);
  466.     else
  467.         sprintf(FuncName, "%s%s", FuncPrefix, funcName);
  468.  
  469.     if (ft = fopen(tmpFile, "w")) {
  470.         if (ProfOpt) {
  471.         fprintf(ft, "\txref\t__ProfInit\n");
  472.         fprintf(ft, "\txref\t__ProfExec\n");
  473.  
  474.         fprintf(ft, "\n\tsection autoinit1,code\n");
  475.         fprintf(ft, "\tlea\tlp0%s,A0\n", DataModel);
  476.         fprintf(ft, "\tjsr\t__ProfInit\n", CodeModel);
  477.         fprintf(ft, "\n\tsection libdata,data\n");
  478.         fprintf(ft, "\tds.l\t0\n");
  479.         fprintf(ft, "lp0\n");
  480.         fprintf(ft, "\tdc.l\t0\n");
  481.         fprintf(ft, "\tdc.l\t0\n");
  482.         fprintf(ft, "\tdc.l\t0\n");
  483.         fprintf(ft, "\tdc.w\t%ld\n", (40 + strlen(FuncName) + (1 + 3)) & ~3);
  484.         fprintf(ft, "\tdc.w\t0\n");
  485.         fprintf(ft, "\tdc.l\t0\n");
  486.         fprintf(ft, "\tdc.l\t0\n");
  487.         fprintf(ft, "\tdc.l\t0\n");
  488.         fprintf(ft, "\tdc.l\t0\n");
  489.         fprintf(ft, "\tdc.l\tlp1\n");
  490.         fprintf(ft, "\tdc.l\tlp2\n");
  491.         fprintf(ft, "\tdc.b\t\'%s\',0\n", FuncName);
  492.  
  493.         fprintf(ft, "\tds.l\t0\n");
  494.         }
  495.         fprintf(ft, "\n\tsection ,code\n\n");
  496.         fprintf(ft, "\txref\t%s\n\n", base);
  497.  
  498.         fprintf(ft, "\txdef\t%s\n", FuncName);
  499.         fprintf(ft, "%s:\n", FuncName);
  500.  
  501.         AddLVOList(funcName, -bias);
  502.  
  503.         if (ProfOpt) {
  504.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  505.         fprintf(ft, "lp1\n");
  506.         }
  507.  
  508.         if (RegOpt == 0 || rs->rn_Args == -1) {    /*  STACK CALL */
  509.         StackCall(ft, base, bias, FRegs, argCnt);
  510.         } else {                    /*  REG CALL   */
  511.         RegsCall(ft, base, bias, rs, FRegs);
  512.         }
  513.         fputs("\tEND\n", ft);
  514.         fclose(ft);
  515.  
  516.         /*
  517.          *    assemble the temp file
  518.          */
  519.  
  520.         if (Verbose)
  521.         puts("");
  522.         if (AssembleFile(tmpFile, objFile))
  523.         JoinOutput(fo, objFile);
  524.         remove(objFile);
  525.         remove(tmpFile);
  526.     } else {
  527.         printf("\tError, Unable to create file: %s\n", tmpFile);
  528.     }
  529.     }
  530. }
  531.  
  532. void
  533. ScanRSTmp(fi)
  534. FILE *fi;
  535. {
  536.     RSNode *rs;
  537.     char *ptr;
  538.     char *symPtr;
  539.  
  540.     while (fgets(Buf, sizeof(Buf), fi)) {
  541.     if (strnicmp(Buf, "##regspec", 9) != 0)
  542.         continue;
  543.  
  544.     for (ptr = Buf + 9; *ptr == ' ' || *ptr == '\t'; ++ptr);
  545.     symPtr = ptr;
  546.     while (*ptr && *ptr != '(')
  547.         ++ptr;
  548.     if (*ptr != '(') {
  549.         printf("Error scanning RS file: %s\n", Buf);
  550.         continue;
  551.     }
  552.     *ptr++ = 0;
  553.     rs = malloc(sizeof(RSNode) + strlen(symPtr) + 1);
  554.     rs->rn_Node.ln_Name = (char *)(rs + 1);
  555.     rs->rn_Flag = 0;
  556.     strcpy(rs->rn_Node.ln_Name, symPtr);
  557.  
  558.     if (*ptr == '*') {
  559.         rs->rn_Args = -1;
  560.         while (*ptr && *ptr != ')')
  561.         ++ptr;
  562.     } else {
  563.         rs->rn_Args = 0;
  564.         while (*ptr && *ptr != ')') {
  565.         switch(*ptr) {
  566.         case 'd':
  567.         case 'D':
  568.             rs->rn_Regs[rs->rn_Args++] = ptr[1] - '0';
  569.             ptr += 2;
  570.             break;
  571.         case 'a':
  572.         case 'A':
  573.             rs->rn_Regs[rs->rn_Args++] = ptr[1] - '0' + 8;
  574.             ptr += 2;
  575.             break;
  576.         default:
  577.             printf("Error, Illegal RS file register spec: %s\n", ptr);
  578.             ptr = "";
  579.             break;
  580.         }
  581.         if (*ptr == ',')
  582.             ++ptr;
  583.         }
  584.     }
  585.     if (*ptr != ')') {
  586.         printf("Error scanning RS file: %s\n", symPtr + strlen(symPtr) + 1);
  587.         continue;
  588.     }
  589.     if (Verbose > 1)
  590.         printf("RS-SCAN: %s (%d)\n", rs->rn_Node.ln_Name, rs->rn_Args);
  591.     AddTail((struct List *)&RSList, &rs->rn_Node);
  592.     }
  593. }
  594.  
  595. int
  596. AssembleFile(inFile, outFile)
  597. char *inFile;
  598. char *outFile;
  599. {
  600.     remove(outFile);
  601.  
  602.     if (Verbose > 2) {
  603.     FILE *fi;
  604.     if (fi = fopen(inFile, "r")) {
  605.         while (fgets(Buf, sizeof(Buf), fi))
  606.         fputs(Buf, stdout);
  607.         fclose(fi);
  608.     }
  609.     }
  610.     sprintf(Buf, "%sdas %s -o %s -nu",
  611.     Prefix,
  612.     inFile,
  613.     outFile
  614.     );
  615. #ifdef unix
  616.     system(Buf);
  617. #else
  618.     Execute(Buf, NULL, NULL);
  619. #endif
  620.     return(1);
  621. }
  622.  
  623. void
  624. JoinOutput(fo, file)
  625. FILE *fo;
  626. char *file;
  627. {
  628.     FILE *fi;
  629.     short c;
  630.  
  631.     if (fi = fopen(file, "r")) {
  632.     while ((c = getc(fi)) != EOF)
  633.         putc(c, fo);
  634.     fclose(fi);
  635.     } else {
  636.     printf("Error, Can't read %s\n", file);
  637.     }
  638. }
  639.  
  640. /*
  641.  *  Generate assembly for a stack based call
  642.  */
  643.  
  644. void
  645. StackCall(FILE *ft, char *base, long bias, short *regs, short args)
  646. {
  647.     uword mask = (RegsToMask(regs, args) | RF_BP) & ~RF_SCRATCH;
  648.     char *ptr;
  649.     short i;
  650.     short j;
  651.     short n;
  652.  
  653.     /*
  654.      *    step 1, what regs need to be saved?
  655.      */
  656.  
  657.     n = PushMask(ft, mask);
  658.  
  659.     /*
  660.      *    step 2, load regs from stack
  661.      */
  662.  
  663.     for (i = j = 0; i < args; i = j) {
  664.     uword lmask = 1 << regs[i];
  665.     short ln;
  666.     int offset = n * 4 + i * 4 + 4;
  667.  
  668.     for (j = i + 1; j < args; ++j) {
  669.         if (regs[j] < regs[j-1])
  670.         break;
  671.         lmask |= 1 << regs[j];
  672.     }
  673.     ptr = RegMaskToStr(lmask, &ln);
  674.     if (ln > 1)
  675.         fprintf(ft, "\tmovem.l\t%d(sp),%s\n", offset, ptr);
  676.     else if (ln > 0)
  677.         fprintf(ft, "\tmove.l\t%d(sp),%s\n", offset, ptr);
  678.     }
  679.     /*
  680.      *    step 3, load library base register
  681.      */
  682.  
  683.     fprintf(ft, "\tmove.l\t%s%s,A%d\n", base, DataModel, RB_BP - 8);
  684.  
  685.     /*
  686.      *    step 4, make call & return
  687.      */
  688.  
  689.     if (n) {
  690.     fprintf(ft, "\tjsr\t-%d(A%d)\n", bias, RB_BP - 8);
  691.     PopMask(ft, mask);
  692.     if (ProfOpt) {
  693.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  694.         fprintf(ft, "lp2\n");
  695.     }
  696.     fprintf(ft, "\tRTS\n");
  697.     } else {
  698.     if (ProfOpt) {
  699.         fprintf(ft, "\tjsr\t-%d(A%d)\n", bias, RB_BP - 8);
  700.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  701.         fprintf(ft, "lp2\n");
  702.         fprintf(ft, "\tRTS\n");
  703.     } else {
  704.         fprintf(ft, "\tjmp\t-%d(A%d)\n", bias, RB_BP - 8);
  705.     }
  706.     }
  707. }
  708.  
  709. /*
  710.  *  Generate assembly for a register based call
  711.  */
  712.  
  713. void
  714. RegsCall(ft, base, bias, rs, regs)
  715. FILE *ft;
  716. char *base;
  717. long bias;
  718. RSNode *rs;
  719. short *regs;
  720. {
  721.     uword mask = (RegsToMask(regs, rs->rn_Args) | RF_BP) & ~RF_SCRATCH;
  722.     short i;
  723.     short j;
  724.     short n;
  725.  
  726.     /*
  727.      *    step 1, what regs need to be saved?
  728.      */
  729.  
  730.     n = PushMask(ft, mask);
  731.  
  732.     /*
  733.      *    step 2, load regs from other regs.  If destination is 'in use',
  734.      *    then use EXG instead (and track where the reg went to)
  735.      *
  736.      *    src:    rs->rn_Regs[i]
  737.      *    dest:    regs[i]
  738.      */
  739.  
  740.     for (i = 0; i < rs->rn_Args; ++i) {
  741.     for (j = 0; j < rs->rn_Args; ++j) { /*    is dest in use? */
  742.         if (i != j && regs[i] == rs->rn_Regs[j])
  743.         break;
  744.     }
  745.     if (j == rs->rn_Args) {         /*  not in use        */
  746.         if (regs[i] != rs->rn_Regs[i]) {    /*  not in right plac    */
  747.         fprintf(ft, "\tmove.l\t%s,%s\n", RegToStr(rs->rn_Regs[i]), RegToStr(regs[i]));
  748.         rs->rn_Regs[i] = -1;
  749.         }
  750.     } else {
  751.         fprintf(ft, "\texg.l\t%s,%s\n", RegToStr(rs->rn_Regs[i]), RegToStr(regs[i]));
  752.         rs->rn_Regs[j] = rs->rn_Regs[i];
  753.         rs->rn_Regs[i] = -1;
  754.     }
  755.     }
  756.  
  757.     /*
  758.      *    step 3, load library base register
  759.      */
  760.  
  761.     fprintf(ft, "\tmove.l\t%s%s,A%d\n", base, DataModel, RB_BP - 8);
  762.  
  763.     /*
  764.      *    step 4, make call and return
  765.      */
  766.  
  767.     if (n) {
  768.     fprintf(ft, "\tjsr\t-%d(A%d)\n", bias, RB_BP - 8);
  769.     PopMask(ft, mask);
  770.  
  771.     if (ProfOpt) {
  772.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  773.         fprintf(ft, "lp2\n");
  774.     }
  775.     fprintf(ft, "\tRTS\n");
  776.     } else {
  777.     if (ProfOpt) {
  778.         fprintf(ft, "\tjsr\t-%d(A%d)\n", bias, RB_BP - 8);
  779.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  780.         fprintf(ft, "lp2\n");
  781.         fprintf(ft, "\tRTS\n");
  782.     } else {
  783.         fprintf(ft, "\tjmp\t-%d(A%d)\n", bias, RB_BP - 8);
  784.     }
  785.     }
  786. }
  787.  
  788. char *
  789. RegMaskToStr(uword mask, short *nr)
  790. {
  791.     static char buf[64];
  792.     char *ptr = buf;
  793.     short i;
  794.     short l = -1;
  795.  
  796.     *nr = 0;
  797.  
  798.     for (i = 0; i < 8; ++i) {
  799.     if (mask & (1 << i)) {
  800.         ++*nr;
  801.         if (l >= 0)
  802.         *ptr++ = '/';
  803.         ptr += sprintf(ptr, "D%d", i);
  804.         l = i;
  805.     }
  806.     }
  807.     for (i = 8; i < 16; ++i) {
  808.     if (mask & (1 << i)) {
  809.         ++*nr;
  810.         if (l >= 0)
  811.         *ptr++ = '/';
  812.         ptr += sprintf(ptr, "A%d", i - 8);
  813.         l = i;
  814.     }
  815.     }
  816.     *ptr = 0;
  817.     return(buf);
  818. }
  819.  
  820. uword
  821. RegsToMask(short *regs, short args)
  822. {
  823.     uword mask = 0;
  824.  
  825.     while (args > 0) {
  826.     mask |= 1 << *regs++;
  827.     --args;
  828.     }
  829.     return(mask);
  830. }
  831.  
  832. char *
  833. RegToStr(short rno)
  834. {
  835.     static char Buf[2][16];
  836.     static short BNo;
  837.     char *ptr = Buf[BNo];
  838.  
  839.     BNo = 1 - BNo;
  840.     if (rno < 8)
  841.     sprintf(ptr, "D%d", rno);
  842.     else
  843.     sprintf(ptr, "A%d", rno - 8);
  844.     return(ptr);
  845. }
  846.  
  847. short
  848. PushMask(FILE *fo, uword mask)
  849. {
  850.     short n;
  851.     char *ptr;
  852.  
  853.     ptr = RegMaskToStr(mask, &n);
  854.     if (n > 1)
  855.     fprintf(fo, "\tmovem.l\t%s,-(sp)\n", ptr);
  856.     else if (n > 0)
  857.     fprintf(fo, "\tmove.l\t%s,-(sp)\n", ptr);
  858.     return(n);
  859. }
  860.  
  861. short
  862. PopMask(FILE *fo, uword mask)
  863. {
  864.     short n;
  865.     char *ptr;
  866.  
  867.     ptr = RegMaskToStr(mask, &n);
  868.     if (n > 1)
  869.     fprintf(fo, "\tmovem.l\t(sp)+,%s\n", ptr);
  870.     else if (n > 0)
  871.     fprintf(fo, "\tmove.l\t(sp)+,%s\n", ptr);
  872.     return(n);
  873. }
  874.  
  875. void
  876. AddLVOList(funcName, bias)
  877. char *funcName;
  878. int bias;
  879. {
  880.     LVONode *node;
  881.  
  882.     if (node = malloc(sizeof(LVONode) + strlen(funcName) + 1)) {
  883.     AddTail(&LVOList, &node->lv_Node);
  884.     node->lv_Node.ln_Name = (char *)(node + 1);
  885.     strcpy(node->lv_Node.ln_Name, funcName);
  886.     node->lv_Offset = bias;
  887.     }
  888. }
  889.  
  890. void
  891. GenerateLVOList(fo)
  892. FILE *fo;
  893. {
  894.     char tmpFile[L_tmpnam];
  895.     char objFile[L_tmpnam + 4];
  896.     LVONode *node;
  897.     FILE *ft;
  898.  
  899.     tmpnam(tmpFile);
  900.     sprintf(objFile, "%s.o", tmpFile);
  901.  
  902.     if (node = RemHead(&LVOList)) {
  903.     if (ft = fopen(tmpFile, "w")) {
  904.         fprintf(ft, "\n\tsection ,code\n\n");
  905.  
  906.         while (node) {
  907.         if (Verbose)
  908.             printf("_LVO%-20s = %d\n", node->lv_Node.ln_Name, node->lv_Offset);
  909.         fprintf(ft, "_LVO%s\tEQU\t%d\n", node->lv_Node.ln_Name, node->lv_Offset);
  910.         fprintf(ft, "\txdef\t_LVO%s\n", node->lv_Node.ln_Name);
  911.         free(node);
  912.         node = RemHead(&LVOList);
  913.         }
  914.         fputs("\tEND\n", ft);
  915.         fclose(ft);
  916.  
  917.         if (AssembleFile(tmpFile, objFile))
  918.         JoinOutput(fo, objFile);
  919.         remove(objFile);
  920.         remove(tmpFile);
  921.     }
  922.     }
  923. }
  924.  
  925. /*
  926.  *  generate auto-open tag code for this library
  927.  */
  928.  
  929. void
  930. GenerateAutoOpen(fo, base)
  931. FILE *fo;
  932. char *base;
  933. {
  934.     char tmpFile[L_tmpnam];
  935.     char objFile[L_tmpnam + 4];
  936.     FILE *ft;
  937.  
  938.     tmpnam(tmpFile);
  939.     sprintf(objFile, "%s.o", tmpFile);
  940.  
  941.     if (ft = fopen(tmpFile, "w")) {
  942.     fprintf(ft, "\n\txdef\t%s\n", base);
  943.     fprintf(ft, "\n\txref\t__AutoFail0\n\n");
  944.     fprintf(ft, "_LVOOpenLibrary\tequ\t-552\n");
  945.     fprintf(ft, "_LVOCloseLibrary\tequ\t-414\n\n");
  946.  
  947.     fprintf(ft, "\n\tsection autoinit0,code\n\n");
  948.  
  949.     fprintf(ft, "\tmoveq.l\t#0,D0\n");
  950.     fprintf(ft, "\tlea\tlibname(pc),A1\n");
  951.     fprintf(ft, "\tjsr\t_LVOOpenLibrary(A6)\n");
  952.     fprintf(ft, "\tmove.l\tD0,%s%s\n", base, DataModel);
  953.     fprintf(ft, "\tbeq\t__AutoFail0\n");
  954.     fprintf(ft, "\tbra\topennext\n");
  955.     fprintf(ft, "libname\tdc.b\t'%s',0\n", SharedLibName);
  956.     fprintf(ft, "\tds.w\t0\n");
  957.     fprintf(ft, "opennext\n\n");
  958.  
  959.     fprintf(ft, "\tsection autoexit0,code\n\n");
  960.     fprintf(ft, "\tmove.l\t%s%s,D0\n", base, DataModel);
  961.     fprintf(ft, "\tbeq\tclosenext\n");
  962.     fprintf(ft, "\tmove.l\tD0,A1\n");
  963.     fprintf(ft, "\tjsr\t_LVOCloseLibrary(A6)\n");
  964.     fprintf(ft, "closenext\n\n");
  965.  
  966.     fprintf(ft, "\tsection libdata,data\n\n");
  967.     fprintf(ft, "%s\tdc.l\t0\n", base);
  968.  
  969.     fputs("\tEND\n", ft);
  970.     fclose(ft);
  971.  
  972.     if (AssembleFile(tmpFile, objFile))
  973.         JoinOutput(fo, objFile);
  974.     remove(objFile);
  975.     remove(tmpFile);
  976.     }
  977. }
  978.  
  979.  
  980. #ifdef LATTICE
  981.  
  982. char *
  983. tmpnam(buf)
  984. char *buf;
  985. {
  986.     static char Buf[L_tmpnam];
  987.     static short Seq;
  988.  
  989.     if (buf == NULL)
  990.     buf = Buf;
  991.     sprintf(buf, "T:%06lx%d", (long)FindTask(NULL) >> 4, Seq++);
  992.     return(buf);
  993. }
  994.  
  995. #endif
  996.  
  997. void
  998. DicePrefix(char *buf, char *av0, char *app)
  999. {
  1000.     char *ptr;
  1001.     short n = 0;
  1002.  
  1003.     for (ptr=av0+strlen(av0); ptr >= av0 && *ptr != '/' && *ptr != ':'; --ptr)
  1004.     ;
  1005.     ++ptr;
  1006.     if (av0 = strchr(ptr, '_')) {
  1007.     n = av0 - ptr + 1;
  1008.     strncpy(buf, ptr, n);
  1009.     }
  1010.     strcpy(buf + n, app);
  1011. }
  1012.  
  1013.